package com.ushine.web.communication.signature.tx;


import com.ushine.web.communication.signature.SignatureHeaders;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;

/**
 * @Author: yls
 * @Date: 2021/12/29 13:14
 * @Description: 腾讯签名 V3
 * @Version 1.0
 */
public class TxSignatureService {
    private final static Charset UTF8 = StandardCharsets.UTF_8;

    /**
     * 功能描述:
     * 〈 加密方式 〉
     *
     * @param key 加密key
     * @param msg 待加密的数据
     * @return : byte[]
     * @author : yls
     * @date : 2021/12/29 14:01
     */
    public static byte[] hmac256(byte[] key, String msg) throws Exception {
        Mac mac = Mac.getInstance("HmacSHA256");
        SecretKeySpec secretKeySpec = new SecretKeySpec(key, mac.getAlgorithm());
        mac.init(secretKeySpec);
        return mac.doFinal(msg.getBytes(UTF8));
    }

    /**
     * 功能描述:
     * 〈 加密方式 〉
     *
     * @param s
     * @return : java.lang.String
     * @author : yls
     * @date : 2021/12/29 14:01
     */
    public static String sha256Hex(String s) throws Exception {
        MessageDigest md = MessageDigest.getInstance("SHA-256");
        byte[] d = md.digest(s.getBytes(UTF8));
        return DatatypeConverter.printHexBinary(d).toLowerCase();
    }

    /**
     * 功能描述:
     * 〈 生成签名，服务端使用〉
     *
     * @param
     * @return : java.lang.String
     * @author : yls
     * @date : 2021/12/29 14:17
     */
    public static String initSignature(SignatureHeaders signatureHeaders, String restFulUrl) throws Exception {
        /**
         * 秘钥对 id
         */
        String appSecretKey = signatureHeaders.getAppSecretKey();
        /**
         * appId
         */
        String appId = signatureHeaders.getAppId();
        /**
         * 时间戳
         */
        String timeStamp = signatureHeaders.getTimeStamp();

        /************* 拼接待签名字符串 *************/
        String hashedRestFulUrl = sha256Hex(restFulUrl);
        String stringToSign = appId + "\n" + timeStamp + "\n" + "\n" + hashedRestFulUrl;
        /************* 计算签名 *************/
        byte[] secretDate = hmac256((appSecretKey).getBytes(UTF8), timeStamp);
        byte[] secretService = hmac256(secretDate, restFulUrl);
        byte[] secretSigning = hmac256(secretService, appId);
        String signature = DatatypeConverter.printHexBinary(hmac256(secretSigning, stringToSign)).toLowerCase();
        return signature;
    }

    /**
     * 功能描述:
     * 〈 生成签名，客户端使用 〉
     *
     * @param appSecretKey 秘钥对的密码
     * @param appId        应用产品id
     * @param timeStamp    时间戳
     * @param restFulUrl   restFul的请求，去除ip、端口
     * @return : java.lang.String
     * @author : yls
     * @date : 2021/12/29 14:32
     */
    public static String initSignature(String appSecretKey, String appId, String timeStamp, String restFulUrl) throws Exception {
        /************* 拼接待签名字符串 *************/
        String hashedRestFulUrl = sha256Hex(restFulUrl);
        String stringToSign = appId + "\n" + timeStamp + "\n" + "\n" + hashedRestFulUrl;
        /************* 计算签名 *************/
        byte[] secretDate = hmac256((appSecretKey).getBytes(UTF8), timeStamp);
        byte[] secretService = hmac256(secretDate, restFulUrl);
        byte[] secretSigning = hmac256(secretService, appId);
        String signature = DatatypeConverter.printHexBinary(hmac256(secretSigning, stringToSign)).toLowerCase();
        return signature;
    }


    public static void main(String[] args) throws Exception {
        /**
         * 应用产品id
         */
        String appId = "88888888";
        /**
         * 秘钥对的id
         */
        String appSecretId = "123456789";
        /**
         * 秘钥对的密码
         */
        String appSecretKey = "987654321";
        /**
         * 时间戳，这里为了测试，固定值
         */
        String timeStamp = "1640052140755";
        SignatureHeaders signatureHeaders = new SignatureHeaders();
        signatureHeaders.setAppId(appId);
        signatureHeaders.setAppSecretId(appSecretId);
        signatureHeaders.setTimeStamp(timeStamp);
        signatureHeaders.setAppSecretKey(appSecretKey);
        String restFulUrl = "/consumerFirst/post";
        String clientSignature = initSignature(appSecretKey, appId, timeStamp,restFulUrl );
        System.out.println("客户端签名："+clientSignature);
        String serverSignature = initSignature(signatureHeaders, restFulUrl);
        System.out.println("服务端签名："+serverSignature);
    }
}
